//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++


Abstract:

    Power Manager Monitor.
    Run in the background to display power state changes in debugger.

Notes:

Revision History:

--*/

//------------------------------------------------------------------------------
//    Revision History
//    Date                  Author                  Activity ID                 Activity Headline
//    2005-6-4           Shi Feng                CNXT00044565                  Add GSM RIL fucntion
//    2006-02-24        Zhangchunzhong           CEDB00007161                  Add trace module in paladin project 
//    2006-03-2         wuguangliang             CEDB00007943                  Add trace module to log irq
//    2006-03-17        wuguangliang             CEDB00010269                  Disable powersaving when power 'on'
//    2006-03-22        wuguangliang             CEDB00010651                  Fix bug when power resume
//    2006-03-31        wuguangliang             CEDB00012163                  Reopen CEDB00010269
//    2006-05-17	    wuguangliang             CEDB200000905                 Merge ppc and smartph into one base
//    2006-08-28        qinxuetao                CEDB200011169                 Add power saving function in RIL
//    2006-09-01        qinxuetao                CEDB200011169                 Enable RIL Driver to enter idle mode
//    2007-02-01        hanshuanghuan            TOSHI00030953                 Update rilhsdpa for power management
//    2007-04-17        qinxuetao                WM600002434                   Modified rilpm for Lampson.
//    2007-04-26        qinxuetao                WM600002433                   Modify the AT string suppressing unsolicited notification.
//------------------------------------------------------------------------------


#include <windows.h>
#include <ceddk.h>
#include <devload.h>
#include <Winreg.h>
#include <Pegdser.h>
/*
#include <Config.h>
#include <Tools.h>
#include <nkintr.h>
#include <Platform.h>
*/
#include "precomp.h"

#include <msgqueue.h>
#include <pm.h>
//#include <tf_oal_ioctl.h>


#define QUEUE_ENTRIES   3
#define MAX_NAMELEN     200
#define QUEUE_SIZE      (QUEUE_ENTRIES * (sizeof(POWER_BROADCAST) + MAX_NAMELEN))

#define STRING_ON _T("on")

int GetPriority(VOID)
{
    return THREAD_PRIORITY_HIGHEST;     // THREAD_PRIORITY_NORMAL
}
DWORD RIL_PmProc (LPVOID lpParameter)
{
    FUNCTION_TRACE(RIL_PmProc);
    DEBUGCHK(lpParameter != NULL);
    CRilHandle* pRilDevice = (CRilHandle*)lpParameter;
    RETAILMSG(MSG_ON, (TEXT("RILDrv : t : RIL_PmProc : Entering, pRilDevice=0x%x\r\n"),pRilDevice));
    const DWORD dwReturn = pRilDevice->PmThread();
    RETAILMSG(MSG_ON, (TEXT("RILDrv : E : RIL_PmProc : THREAD IS EXITING, dwReturn=0x%x\r\n"),dwReturn));
    return dwReturn;
}
DWORD CRilHandle::PmThread ()
{
    HANDLE hMsgQ = NULL;
    HANDLE hNotifications = NULL;
    DWORD dwErr, dwFlags = 0, dwCount = 0;
    DWORD dwPri = CeGetThreadPriority(GetCurrentThread());
    
    MSGQUEUEOPTIONS msgOptions = {0};   

    UCHAR buf[QUEUE_SIZE];
    unsigned long iBytesInQueue;
    
	//added by wuguangliang to identify whether the gsm would report status
#ifdef BSP_POCKETPC
    BOOL bDisableGSMREP = FALSE;
#endif 

    // create a message queue for Power Manager notifications
    //
    msgOptions.dwSize = sizeof(MSGQUEUEOPTIONS);
    msgOptions.dwFlags = 0;
    msgOptions.dwMaxMessages = QUEUE_ENTRIES;
    msgOptions.cbMaxMessage = sizeof(POWER_BROADCAST) + MAX_NAMELEN;
    msgOptions.bReadAccess = TRUE;

    hMsgQ = CreateMsgQueue(NULL, &msgOptions);
    if (!hMsgQ) {
        dwErr = GetLastError();
        RETAILMSG(MSG_ON, (TEXT("PMMON!CreateMessageQueue ERROR:%d\r\n"), dwErr));
        goto _Exit;
    }

    // request Power notifications
    //
    hNotifications = RequestPowerNotifications(hMsgQ, POWER_NOTIFY_ALL); // Flags
    if (!hNotifications) {
        dwErr = GetLastError();
        RETAILMSG(MSG_ON, (TEXT("PMMON!RequestPowerNotifications ERROR:%d\r\n"), dwErr));
        goto _Exit;
    }

    dwPri = GetPriority();
    if ( !SetThreadPriority(GetCurrentThread(), dwPri)) {
        dwErr = GetLastError();
        RETAILMSG(MSG_ON, (TEXT("PMAPI!SetThreadPriority ERROR:%d\r\n"), dwErr));
        goto _Exit;
    }

    while (1) 
    {
        iBytesInQueue = 0;
        memset(&buf, 0, QUEUE_SIZE);

        // Block on our message queue.
        // This thread runs when the power manager writes a notification into the queue.
        if ( !ReadMsgQueue(hMsgQ,
                           &buf,
                           QUEUE_SIZE,
                           &iBytesInQueue,
                           INFINITE,    // Timeout
                           &dwFlags))
        {
            dwErr = GetLastError();
            RETAILMSG(MSG_ON, (TEXT("PMMON!ReadMsgQueue: ERROR:%d\r\n"), dwErr));
            ASSERT(0);
        } else if(iBytesInQueue >= sizeof(POWER_BROADCAST)) {
            //
            // process power notifications
            //
            PPOWER_BROADCAST pB = (PPOWER_BROADCAST)&buf;
            
            RETAILMSG(MSG_ON, (TEXT("PMMON!*** Power Notification @ Tick:%u, Count:%d, Pri:%d***\r\n"), 
                GetTickCount(), dwCount++, dwPri));
            switch (pB->Message) 
            {
            case PBT_TRANSITION:
                RETAILMSG(MSG_ON, (TEXT("PMMON!\tPBT_TRANSITION to system power state: '%s'\r\n"), pB->SystemPowerState));
                switch (POWER_STATE(pB->Flags)) {
                case POWER_STATE_ON:
                    RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tPOWER_STATE_ON\r\n")));
                    break;
                case POWER_STATE_OFF:
                    RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tPOWER_STATE_OFF\r\n")));
                    break;
                case POWER_STATE_CRITICAL:
                    RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tPOWER_STATE_CRITICAL\r\n")));
                    break;
                case POWER_STATE_BOOT:
                    RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tPOWER_STATE_BOOT\r\n")));
                    break;
                case POWER_STATE_IDLE:
                    RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tPOWER_STATE_IDLE\r\n")));
                    break;
                case POWER_STATE_SUSPEND:
                    RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tPOWER_STATE_SUSPEND\r\n")));
#ifdef OEM1_DRIVER
#ifdef BSP_POCKETPC
                    RETAILMSG(MSG_ON, (TEXT("RilDrv: Power suspend...........\r\n")));
                    bDisableGSMREP = TRUE;
                    RILDrv_EnablePowerSavings(0);
#endif // BSP_POCKETPC
#endif // OEM1_DRIVER
                    break;
                case POWER_STATE_RESET:
                    RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tPOWER_STATE_RESET\r\n")));
                    break;
                case POWER_STATE_UNATTENDED:
                    RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tPOWER_STATE_UNATTENDED\r\n")));
#if defined(BSP_POCKETPC) && defined(WAVECOM_DRIVER)
                    {  
                        RETAILMSG(MSG_ON,(TEXT("RilDrv: Power suspend...........\r\n")));
                        //CHAR* szCmd = "AT+CREG=0;+CGREG=0;+TCFG=\"IND\",0\r";
                        CHAR* szCmd = "AT+TCFG=\"IND\",0\r";
                        if(m_pComDevice->WriteCharsToComPort(this, szCmd, strlen(szCmd)))
                        {
                            RETAILMSG(MSG_ON,(TEXT("RilDrv: Deactive unsolicited result...........\r\n")));
                        }
                    }
#endif
                    break;
                case POWER_STATE_USERIDLE:
                    RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tPOWER_STATE_USERIDLE\r\n")));
#if !defined(BSP_POCKETPC) && defined(WAVECOM_DRIVER)
                    RILDrv_EnablePowerSavings(0);
#endif
                    break;
                case POWER_STATE_PASSWORD:
                    RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tPOWER_STATE_PASSWORD\r\n")));
                    break;
                case 0x10010000:
                    RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tUNKNOWN STATE 0x10010000\r\n")));
#ifdef OEM1_DRIVER
#ifdef BSP_POCKETPC
                    if (_tcsicmp(pB->SystemPowerState,STRING_ON)==0)
                    {
                        if (bDisableGSMREP)
                        {
                            bDisableGSMREP = FALSE;
                            RILDrv_DisablePowerSavings(0);
                        }
                    }
 #endif //POCKETPC
 #endif
                    break;
                case 0x12010000:
                    RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tUNKNOWN STATE 0x12010000\r\n")));
#if !defined(BSP_POCKETPC) && defined(WAVECOM_DRIVER)
                    RILDrv_DisablePowerSavings(0);
#endif         
                    break;
                case 0:
                    break;
                default:
                    RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tUnknown Power State Flags:0x%x\r\n"),pB->Flags));
                    ASSERT(0);
                    break;
                }
                break;
                
            case PBT_RESUME:
                RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tPBT_RESUME\r\n")));
#ifdef OEM1_DRIVER
#ifdef BSP_POCKETPC
                RETAILMSG(MSG_ON,(L"^^^^^^^^^^^^^^RILPM  system power resume \r\n "));
                //Log the last  weaken source 
                DWORD dwRet;
                UINT32 WakeUpInt;

                if (KernelIoControl(
                    IOCTL_HAL_GET_WAKEUP_INT, NULL, 0,
                    (LPVOID)&WakeUpInt, sizeof(UINT32), &dwRet))
                {
                    RETAILMSG(MSG_ON,(L"^^^^^^^^^^^^^^IOCTL_HAL_GET_WAKEUP_INT  is  %d \r\n ", WakeUpInt));
                } //end of log wake source
#endif // BSP_POCKETPC
#endif // OEM1_DRIVER
#if defined(BSP_POCKETPC) && defined(WAVECOM_DRIVER)
                RILDrv_DisablePowerSavings(0);
#endif
                break;
                    
            case PBT_POWERSTATUSCHANGE:
                RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tPBT_POWERSTATUSCHANGE\r\n")));
                break;
                    
            case PBT_POWERINFOCHANGE:
            {
                RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tPBT_POWERINFOCHANGE\r\n")));

                PPOWER_BROADCAST_POWER_INFO ppbpi = (PPOWER_BROADCAST_POWER_INFO) pB->SystemPowerState;

                RETAILMSG(MSG_ON, (TEXT("PMMON!\tPBT_POWERINFOCHANGE\r\n")));
                RETAILMSG(MSG_ON, (TEXT("PMMON!\t\tAC line status %u, battery flag %u, backup flag %u, %d levels\r\n"),
                            ppbpi->bACLineStatus, ppbpi->bBatteryFlag, ppbpi->bBackupBatteryFlag, ppbpi->dwNumLevels));
                RETAILMSG(MSG_ON, (TEXT("PMMON!\t\tbattery life %d, backup life %d\r\n"),
                            ppbpi->bBatteryLifePercent, ppbpi->bBackupBatteryLifePercent));
                RETAILMSG(MSG_ON, (TEXT("PMMON!\t\tlifetime 0x%08x, full lifetime 0x%08x\r\n"),
                            ppbpi->dwBatteryLifeTime, ppbpi->dwBatteryFullLifeTime));
                RETAILMSG(MSG_ON, (TEXT("PMMON!\t\tbackup lifetime 0x%08x, backup full lifetime 0x%08x\r\n"),
                            ppbpi->dwBackupBatteryLifeTime, ppbpi->dwBackupBatteryFullLifeTime));
            }
                break;
                    
            default:
                RETAILMSG(MSG_ON, (TEXT("RilDrv: PMMON!\tUnknown Message:%d\r\n"), pB->Message));
                ASSERT(0);
                break;
            }

            RETAILMSG(MSG_ON, (TEXT("PMMON!\tMessage: 0x%x\r\n"), pB->Message));
            RETAILMSG(MSG_ON, (TEXT("PMMON!\tFlags: 0x%x\r\n"), pB->Flags));
            RETAILMSG(MSG_ON, (TEXT("PMMON!\tdwLen: %d\r\n"), pB->Length));
            RETAILMSG(MSG_ON, (TEXT("PMMON!***********************\r\n")));
        }
        else
        {
            RETAILMSG(MSG_ON, (TEXT("PMMON!\tReceived short message: %d bytes\r\n"), iBytesInQueue));
            ASSERT(0);
        }
    }

_Exit:
    if (hMsgQ)
    {
        CloseMsgQueue(hMsgQ);
    }
    if (hNotifications && !StopPowerNotifications(hNotifications)) {
        RETAILMSG(MSG_ON, (TEXT("PMMON!StopNotifications ERROR:%d\r\n"), GetLastError()));
        ASSERT(0);
    }

    ExitThread(ERROR_SUCCESS);  
    return ERROR_SUCCESS;
}

// EOF
